/*
 *copyright (C) 2015-2018 Alibaba Group Holding Limited
 */

#include <aos/hal/gpio.h>
#include "app_main.h"
#include "vendor.h"
#include "device_state_manger.h"
#include "smart_outlet.h"

#define LED_GPIO   PB0
#define RELAY_GPIO PB1
#define KEY_GPIO   PA0

static gpio_dev_t io_led;
static gpio_dev_t io_key;
static gpio_dev_t io_relay;

static int led_state = -1;
void       product_set_led(bool state)
{
    if (led_state == (int)state) {
        return;
    }

    if (state) {
        hal_gpio_output_high(&io_led);
    } else {
        hal_gpio_output_low(&io_led);
    }

    led_state = (int)state;
}

static bool product_get_led()
{
    return (bool)led_state;
}

void product_toggle_led()
{
    if (product_get_led() == ON) {
        product_set_led(OFF);
    } else {
        product_set_led(ON);
    }
}

static int switch_state = -1;
void       product_init_switch(void)
{
    int state = ON;
    int len   = sizeof(int);
    int ret   = 0;

#if (REBOOT_STATE == LAST_STATE)
    ret = aos_kv_get(KV_KEY_SWITCH_STATE, (void *)&state, &len);
    LOGD(TAG, "get kv save switch state:%d, ret:%d", state, ret);
    if (ret != 0)
        state = ON;
#elif (REBOOT_STATE == POWER_OFF)
    state == OFF;
#else
    state == ON;
#endif
    if (state == OFF) {
        product_set_switch(OFF);
    } else {
        product_set_switch(ON);
    }
}

#if (REBOOT_STATE == LAST_STATE)
aos_timer_t g_timer_period_save_device_status;
#define PERIOD_SAVE_DEVICE_STATUS_INTERVAL (1000 * 30)

static void timer_period_save_device_status_cb(void *arg1, void *arg2)
{
    int state, len = sizeof(int);
    int ret;

    ret = aos_kv_get(KV_KEY_SWITCH_STATE, (void *)&state, &len);

    if (ret != 0 || state != switch_state) {
        LOGD(TAG, "KV DEVICE_STATUS Update!!!,ret=%d.\n", ret);
        ret = aos_kv_set(KV_KEY_SWITCH_STATE, &switch_state, len, 0);
        if (ret < 0)
            LOGE(TAG, "KV set Error: %d\r\n", __LINE__);
    }
}
#endif

void vendor_update_switch_state(void)
{
    int state, len = sizeof(int);
    int ret;

    ret = aos_kv_get(KV_KEY_SWITCH_STATE, (void *)&state, &len);
    if (ret != 0 || state != switch_state) {
        LOGD(TAG, "KV DEVICE_STATUS Update!!!,ret=%d.\n", ret);
        ret = aos_kv_set(KV_KEY_SWITCH_STATE, &switch_state, len, 0);
        if (ret < 0)
            LOGE(TAG, "KV set Error: %d\r\n", __LINE__);
    }
}

void vendor_product_init(void)
{
    io_led.port   = LED_GPIO;
    io_relay.port = RELAY_GPIO;
    io_key.port   = KEY_GPIO;

    io_led.config   = OUTPUT_PUSH_PULL;
    io_relay.config = OUTPUT_PUSH_PULL;
    io_key.config   = INPUT_PULL_UP;

    drv_pinmux_config(KEY_GPIO, PIN_FUNC_GPIO);

    hal_gpio_init(&io_led);
    hal_gpio_init(&io_relay);
    hal_gpio_init(&io_key);

    product_init_switch();
#if (REBOOT_STATE == LAST_STATE)
    aos_timer_new(&g_timer_period_save_device_status, timer_period_save_device_status_cb, NULL,
                  PERIOD_SAVE_DEVICE_STATUS_INTERVAL, 1);
#endif
}

void product_set_switch(bool state)
{
    int ret = 0;

    //LOGD(TAG, "product_set_switch, state:%d, switch_state:%d", state, switch_state);
    if (switch_state == (int)state) {
        return;
    }

    if (state) {
        hal_gpio_output_high(&io_relay);
    } else {
        hal_gpio_output_low(&io_relay);
    }

    switch_state = (int)state;
    product_set_led(state);

    update_power_state(state);

    vendor_update_switch_state();
}

bool product_get_switch(void)
{
    return (bool)switch_state;
}

bool product_get_key(void)
{
    uint32_t level = 0;
    hal_gpio_input_get(&io_key, &level);
    return level;
}

int set_device_meta_info(void)
{
    char product_key[PRODUCT_KEY_LEN + 1]       = {0};
    char product_secret[PRODUCT_SECRET_LEN + 1] = {0};
    char device_name[DEVICE_NAME_LEN + 1]       = {0};
    char device_secret[DEVICE_SECRET_LEN + 1]   = {0};

    memset(product_key, 0, sizeof(product_key));
    memset(product_secret, 0, sizeof(product_secret));
    memset(device_name, 0, sizeof(device_name));
    memset(device_secret, 0, sizeof(device_secret));

    HAL_GetProductKey(product_key);
    HAL_GetProductSecret(product_secret);
    HAL_GetDeviceName(device_name);
    HAL_GetDeviceSecret(device_secret);

    if ((strlen(product_key) > 0) && (strlen(product_secret) > 0) && (strlen(device_name) > 0) &&
        (strlen(device_secret) > 0)) {
        HAL_SetProductKey(product_key);
        HAL_SetProductSecret(product_secret);
        HAL_SetDeviceName(device_name);
        HAL_SetDeviceSecret(device_secret);
        LOGD(TAG, "pk[%s]", product_key);
        LOGD(TAG, "dn[%s]", device_name);
        return 0;
    } else {
        LOGE(TAG, "no valid device meta data");
        return -1;
    }
}

void vendor_device_bind(void)
{
    set_net_state(APP_BIND_SUCCESS);
}

void vendor_device_unbind(void)
{
    linkkit_reset(NULL);
}
void vendor_device_reset(void)
{
    /* do factory reset */
    // clean kv ...
    // clean buffer ...
    /* end */
    do_awss_reset();
}
